<?php

namespace app\reserve\validate;

use think\Validate;
use think\Db;

/**
 * Class Order
 * @package app\reserve\validate
 * @author zhenHong~
 * 订单验证器
 */
class Order extends Validate
{
    protected $rule = [
        'a_id' => 'require',
        'u_id' => 'require|checkDefaultAddress',
        'type' => 'require|checkUserToCashLocation',
        'reservedate' => 'require',
        'reservetime' => 'require',
        'car_id' => 'require',
        'name' => 'require',
        'phone' => ['require', 'regex' => '0?(13|14|15|17|18|19)[0-9]{9}'],
        'updooraddress' => 'checkAddress',
        'machineoil' => 'require|checkOilStock|checkChooseGoods',
        'product' => 'require|checkProductStock|checkChooseGoods',
        'total_price' => 'require',
        'pay_price' => 'require',
        'discounts_price' => 'require',
        'ordernumber' => 'require',
        'deletordder' => 'require',
        'order_id' => 'require'
    ];

    protected $message = [
        'a_id' => '商户参数错误',
        'a_id.checkOrderStatusNumber' => '您选择的保养时间段已经约满,请重新选择',
        'type.require' => '参数错误',
        'type.checkUserToCashLocation' => '默认地址不在商家的服务半径内',
        'u_id.require' => '用户参数错误',
        'u_id.checkDefaultAddress' => '请完善你的资料或填写默认地址',
        'reservedate' => '请选择日期',
        'reservetime' => '请选择时间段',
        'car_id' => '请选择车辆',
        'name' => '请填写姓名',
        'phone' => '手机格式错误',
        'machineoil.require' => '请选择机油',
        'machineoil.checkOilStock' => '机油库存不足',
        'machineoil.checkChooseGoods' => '至少选择一样商品',
        'product.require' => '请选择产品',
        'product.checkProductStock' => '商品库存不足',
        'product.checkChooseGoods' => '至少选择一样商品',
        'total' => '总金额错误',
        'pay_price' => '支付金额错误',
        'discounts_price' => '优惠前金额错误',
        'ordernumber' => '参数错误',
        'ordernumber.checkOrderStatusNumber' => '您选择的保养时间段已经约满,请重新选择',
        'order_id' => '参数错误',
        'order_id.checkBackTime' => '退款时间已过期,不能退款',
        'deletordder' => '请选择取消订单原因'
    ];

    protected $scene = [
        //  生成订单
        'createMyOrder' => [
            'a_id' => ['require', 'checkOrderStatusNumber'],
            'u_id', 'type', 'reservedate', 'reservetime', 'car_id', 'machineoil', 'product', 'total_price', 'pay_price', 'discounts_price'
        ],
        //  更新下单用户信息
        'saveUserOrderInfo' => [
            'name', 'phone',
            'ordernumber' => ['require','checkOrderStatusNumber']
        ],
        //  用户取消订单
        'resetOrder' => ['ordernumber', 'deletordder'],
        //  用户退款
        'handleBackMoney' => [
            'order_id' => ['require', 'checkBackTime']
        ]
    ];

    /**
     * @param $value
     * @param $rules
     * @param $data
     * @return bool
     * 检查订单类型是否为：上门服务 ? 检查 updooraddress-上门服务地址为必填项 : true
     */
    protected function checkAddress($value, $rules, $data)
    {
        if ($data['type'] == 2) {
            if (!isset($data['updooraddress']) || empty($value)) {
                return false;
            }
        }
        return true;
    }

    /**
     * @param $value
     * @param $rule
     * @param $data
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenhong~
     * 根据 type 判断 1:预约到店 2:上门服务
     *      若type=1 则判断,用户的个人信息是否完善(姓名 与 电话)
     *      若type=2 则判断，判断用户是否存在默认地址
     */
    protected function checkDefaultAddress($value, $rule, $data)
    {
        if ($data['type'] == 1) {
            $user = Db::name('User')->where('u_id', $value)->field('name,phone')->find();
            $bool = ($user['name'] && $user['phone']) ? true : false;
        } else {
            $where = [
                'status' => 2,
                'u_id' => $value
            ];
            $address = Db::name('Useraddress')->where($where)->value('id');
            $bool = $address ? true : false;
        }

        return $bool;
    }

    /**
     * @param $value
     * @param $rule
     * @param $data
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenhong~
     * 如果用户选择了,上门保养则要判断，用户位置是否在商家的服务半径之内
     */
    protected function checkUserToCashLocation($value, $rule, $data)
    {
        if ($data['type'] == 2) {

            $where = [
                'status' => 2,
                'u_id' => $data['u_id']
            ];
            //  获取用户默认地址的经纬度
            $userLocation = Db::name('Useraddress')->where($where)->field('lat,lon')->find();

            //  获取商户的经纬度
            $cashLoaction = Db::name('Cash')->where('a_id', $data['a_id'])->field('lat,lon,service_radius')->find();

            //  获取距离
            $distance = getDistance($cashLoaction['lat'], $cashLoaction['lon'], $userLocation['lat'], $userLocation['lon']);

            if ($distance < $distance / 1000) {
                return false;
            }
        }
        return true;
    }

    /**
     * @param $value
     * @return bool
     * @author zhenHong~
     * 验证所选 机油 库存是否充足
     */
    protected function checkOilStock($value)
    {
        $arr = json_decode($value, true);
        $clist = $plist = [];

        //  将平台机油id 与 商户机油id 分别存入两数组
        foreach ($arr as $key => $value) {
            if (array_key_exists('a_id', $value)) {
                $clist[] = $value['id'];
            } else {
                $plist[] = $value['id'];
            }
        }
        //  若选择了商户自己添加的机油，则循环判断商户的库存
        if ($clist) {
            $stock = DB::name('Machineoilforcash')->whereIn('id', $clist)->column('inventory');
            foreach ($stock as $item) {
                if (empty($item)) {
                    return false;
                }
            }
        }

        //  若选择了平台添加的机油，则循环判断平台的库存
        if ($plist) {
            $stock = DB::name('Machineoil')->whereIn('id', $plist)->column('inventory');
            foreach ($stock as $item) {
                if (empty($item)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * @param $value
     * @return bool
     * @author zhenHong~
     * 检查所选商品库存
     */
    protected function checkProductStock($value)
    {
        $arr = json_decode($value, true);
        $clist = $plist = [];

        //  将平台商品id 与 商户商品id 分别存入两数组
        foreach ($arr as $key => $value) {
            if (array_key_exists('a_id', $value)) {
                $clist[] = $value['id'];
            } else {
                $plist[] = $value['id'];
            }
        }

        //  若选择了商户自己添加的商品，则循环判断商户的库存
        if ($clist) {
            $stock = DB::name('Commodityforcash')->whereIn('id', $clist)->column('inventory');
            foreach ($stock as $item) {
                if (empty($item)) {
                    return false;
                }
            }
        }

        //  若选择了平台添加的商品，则循环判断平台的库存
        if ($plist) {
            $stock = DB::name('Commodity')->whereIn('id', $plist)->column('inventory');
            foreach ($stock as $item) {
                if (empty($item)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * @param $value
     * @param $rule
     * @param $data
     * @return bool
     * @author zhenhong~
     */
    protected function checkChooseGoods($value, $rule, $data)
    {
        $arrOil = json_decode($data['machineoil'], true);
        $arrProduct = json_decode($data['product'], true);
        if (!$arrOil && !$arrProduct) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * @param $value
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenhong~
     * 检查退款时间
     */
    protected function checkBackTime($value)
    {
        $time = time();

        $info = Db::name('Order')->where(['id' => $value])->field('a_id,utime')->find();

        $offTime = Db::name('Cash')->where(['a_id' => $info['a_id']])->value('off_order_time');

        if ((intval($info['utime']) + intval($offTime) * 60) >= $time) {
            return true;
        } else {
            return false;
        }
    }


    /**
     * @param $value
     * @param $rule
     * @param $data
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenhong~
     * 创建订单 和 支付时 都要 检查待服务状态的订单数量
     */
    protected function checkOrderStatusNumber($value, $rule, $data)
    {
        if (array_key_exists('ordernumber', $data)) {
            $info = Db::name('Order')->where(['ordernumber' => $data['ordernumber']])->field('reservedate,reservetime,a_id')->find();
            $where = [
                'reservedate' => $info['reservedate'],
                'reservetime' => $info['reservetime'],
                'a_id' => $info['a_id'],
                'status' => 2
            ];
            $orderNum = Db::name('Order')->where($where)->count('id');
            //  对应商户允许时间段 允许保养保养人数
            $arr = explode('-', $info['reservetime']);
            $time = [
                'a_id' => $info['a_id'],
                'starttime' => $arr[0],
                'endtime' => $arr[1]
            ];
        } else {
            //  状态为 待服务的订单数
            $where = [
                'reservedate' => $data['reservedate'],
                'reservetime' => $data['reservetime'],
                'a_id' => $data['a_id'],
                'status' => 2
            ];
            $orderNum = Db::name('Order')->where($where)->count('id');
            //  对应商户允许时间段 允许保养保养人数
            $arr = explode('-', $data['reservetime']);
            $time = [
                'a_id' => $data['a_id'],
                'starttime' => $arr[0],
                'endtime' => $arr[1]
            ];
        }

        $allowNum = Db::name('Timemanage')->where($time)->value('all_num');

        if ($orderNum >= $allowNum) {
            return false;
        } else {
            return true;
        }
    }
}